<?php
namespace ChannelThrift\Controller;
include 'WeaverAuctionTestCase.class.php';

use \Think\PhpUnit;
use \Thrift\Protocol\TBinaryProtocol;
use \Thrift\Protocol\TMultiplexedProtocol;
use \Thrift\Transport\THttpClient;
use \Thrift\Transport\TBufferedTransport;
use \Thrift\Exception\TException;

global $isClean;
$isClean = true;

/**
 * 保证金服务单元测试;
    使用示例:
    phpunit ../Tests/BailControllerTest.class.php
    phpunit ../Tests/BailControllerTest.class.php --group GetBail        
    phpunit ../Tests/BailControllerTest.class.php --group IncBail        
    phpunit ../Tests/BailControllerTest.class.php --group Freeze  
    phpunit ../Tests/BailControllerTest.class.php --group UnFreeze 
    phpunit ../Tests/BailControllerTest.class.php --group DecAndUnFreeze    
    phpunit ../Tests/BailControllerTest.class.php --group DecBail

 * @requires extension mysqli 
 * @requires extension redis
 * @requires extension PHP 5.4.45 
 */
class BailControllerTest extends WeaverAuctionTestCase
{

    private $client = null;
    private $redis = null;
    private $dealerID = 238;
    private $orderID = 2570;
    private $redisDatabase = 0;
    
    /**
        @param serviceName 服务模块名
        @param servicePath 服务路径
        @param serviceDomain 服务域名
        @param servicePort 服务端口
        @return thriftclient 
    */
    private function getThriftClient($serviceName,$servicePath,$serviceDomain,$servicePort=80)
    {      
        if (!$serviceName){
            //抛出异常            
            return false;
        }
        $handle = new THttpClient($serviceDomain, $servicePort, $servicePath);
        $transport = new TBufferedTransport($handle);
        $protocol = new TBinaryProtocol($transport);
        $auctionProtocol = new TMultiplexedProtocol($protocol, $serviceName);
        $serviceName='\\Services\\'.$serviceName.'\\'.$serviceName.'Client';
        $client = new $serviceName($auctionProtocol);
        return $client;        
    }

    private function getRedis(){        
        $config = require ROOT_PATH.'Application/ChannelThrift/Conf/redis.php';        
        $redis = new \Redis();
        $redis->connect($config['REDIS_HOST'],$config['REDIS_PORT']);
        $redis->select($this->redisDatabase);
        return $redis;
    }

    /**
        @before 
    */
    public function testThriftClient(){
        $client = $this->getThriftClient('BailService','/Bail/run','songaimin.auction.weaver.s.isou365.cn'); 
        $this->client = $client;
        $this->redis = $this->getRedis();
    }

    /**
        检查入队列的格式
    */
    private function chkQueueContent(&$QueueContent){
        $this->assertArrayHasKey('summary',$Bail);        
        $this->assertArrayHasKey('log',$Bail);
    }
    /**
        检查接口返回的格式        
    */
    private function chkThriftReturnBail(&$return){        
        $this->assertTrue(is_object($return));
        $this->assertInstanceOf('\Services\BailService\Bail',$return);
        $data  = $return->data;
        $this->assertArrayHasKey('dealer_id',$data);
        $this->assertArrayHasKey('bail_amount',$data);
        $this->assertArrayHasKey('freeze_amount',$data);
        $this->assertArrayHasKey('indemnity_amount',$data);
        $this->assertArrayHasKey('bail_amount',$data);
        $this->assertArrayHasKey('dealer_id',$data);
    }

    /**
        获取车商保证金概要验证
        @group GetBail
    */
    public function testGetDealerBail()
    {
        echo __METHOD__ ."\n";
        $client = $this->client;
        $dealerID = $this->dealerID;

        echo "从mysql获取\n";
        $Key = 'AuctionWeaver:Bail:DealerBailSummary:SpecVar:'.$dealerID;
        $redis = $this->redis;
        $redis->del($Key);
        $bailinfo = $client->getDealerBail($dealerID);
        $this->chkThriftReturnBail($bailinfo);
        $bailinfo = $bailinfo->data;

        $this->assertTrue($bailinfo['dealer_id'] == $dealerID);
        //print_r($bailinfo);
        

        echo "从redis获取\n";        
        $bailinfo = $client->getDealerBail($dealerID);        
        $this->chkThriftReturnBail($bailinfo);
        $bailinfo = $bailinfo->data;
        $this->assertTrue($bailinfo['dealer_id'] == $dealerID);        

        return $bailinfo;
    }

    
    
    /**
        充值验证
        @group IncBail        
        @group Freeze  
        @group UnFreeze 
        @group DecAndUnFreeze     
        @group DecBail
    */
    public function testIncBail()
    {
        echo __METHOD__ ."\n";
        
        $client = $this->client;   
        $dealerID = $this->dealerID;        
        $addAmount = 2000;
        $detail = '保证金充值';
        $rechargeNo = '100';
        $rechargeId = '1000';
        $rechargeMethod = '10000';
        $collectionId = '100000';
        $bail = $client->incBail($dealerID, $addAmount, $detail, $rechargeNo, $rechargeId, $rechargeMethod,$collectionId);      
              
        $this->chkThriftReturnBail($bail);

        $redis = $this->redis;                                
        $data = json_decode($redis->lIndex('AuctionWeaver:Bail:ChangeQueue',-1),true);
        // echo json_encode($data,JSON_UNESCAPED_UNICODE);
        //print_r($data);
        $this->assertTrue(array_key_exists('summary', $data));
        $this->assertTrue(array_key_exists('log', $data));
        $log = $data['log'];
        $this->assertTrue($log['dealer_id']==$dealerID );
        $this->assertTrue(time()-strtotime($log['use_time'])<10);
        $this->assertTrue($log['use_type']==1);
        $this->assertTrue( $log['occur_money']==$addAmount );
        $this->assertTrue( $log['recharge_method']==$rechargeMethod );
        $this->assertTrue( $log['recharge_no']==$rechargeNo );
        $this->assertTrue( $log['recharge_id']==$rechargeId );
        $this->assertTrue( $log['use_detail']==$detail);
        $this->assertTrue( $log['collection_id']==$collectionId);
        $this->assertTrue( $data['summary']['bail_amount']-$addAmount == $log['remain_amount']-$addAmount );
        $this->assertTrue( $data['summary']['dealer_id'] == $dealerID );

        $this->lPopLast1();
        
        
    }

   
    /**
        测试冻结        
        @group Freeze
        @group UnFreeze    
        @group Exception     
    */
    public function testFreezeBail()
    {
        echo __METHOD__ ."\n";
        
        $client = $this->client;   
        $dealerID = $this->dealerID;        
        $addAmount = 2000;
        $orderId = $this->orderID;
        
        $before_freeze_bail = $client->getDealerBail($dealerID);
        $before_freeze_bail = $before_freeze_bail->data;
        //执行冻结
        $bail = $client->freezeBail($dealerID, $addAmount, $orderId);
        $this->chkThriftReturnBail($bail);
        $after_freeze_bail = $client->getDealerBail($dealerID);
        $after_freeze_bail = $after_freeze_bail->data;
        //验证冻结
        $detail = '冻结保证金,拍单:'.$orderId;
        $redis = $this->redis;                                
        $data = json_decode($redis->lIndex('AuctionWeaver:Bail:ChangeQueue',-1),true);  
        // echo json_encode($data,JSON_UNESCAPED_UNICODE);           
        //print_r($data);
        $this->assertTrue(array_key_exists('summary', $data));
        $this->assertTrue(array_key_exists('log', $data));
        $log = $data['log'];
        $this->assertTrue($log['dealer_id']==$dealerID );
        $this->assertTrue(time()-strtotime($log['use_time'])<10);
        $this->assertTrue($log['use_type']==2);
        $this->assertTrue( $log['occur_money']==$addAmount );
        $this->assertTrue( $log['recharge_method']==0);
        $this->assertTrue( $log['recharge_no']==0 );
        $this->assertTrue( $log['recharge_id']==0 );
        $this->assertTrue( $log['use_detail']==$detail);
        $this->assertTrue( $log['collection_id']==0);

        $this->assertTrue( $after_freeze_bail['bail_amount'] == ($before_freeze_bail['bail_amount']-$addAmount) );
        $this->assertTrue( $data['summary']['bail_amount'] == ($before_freeze_bail['bail_amount']-$addAmount) );
        $this->assertTrue( $data['summary']['freeze_amount'] == ($before_freeze_bail['freeze_amount']+$log['occur_money']));            
        $this->assertTrue( $data['summary']['dealer_id'] == $dealerID );

        
        $this->lPopLast1();
        
    }

    /**
        测试解冻异常
        @group Exception
        */
    public function testExceptionForUnFreezeBail(){
        echo __METHOD__ ."\n";
        //解冻
        try{
            //车商为空
            $this->client->unfreezeBail($dealerID, $this->orderID);
        }catch(TException $e){
            $this->assertTrue($e->getCode()==10015);
        }
        try{
            //拍单为空
            $this->client->unfreezeBail($this->dealerID, 0);
        }catch(TException $e){
            $this->assertTrue($e->getCode()==500053);
        }

        //扣除并解冻
        try{
            //车商为空
            $this->client->unfreezeDecBail(0 , $this->orderID , 500, 0, '');
        }catch(TException $e){
            $this->assertTrue($e->getCode()==10001);
        }
        try{
            //拍单为空 
            $this->client->unfreezeDecBail($this->dealerID , 0 , $deductAmount, 0, '');
        }catch(TException $e){
            $this->assertTrue($e->getCode()==700002);
        }
        try{
            //超大金额
            $this->client->unfreezeDecBail($this->dealerID , $this->orderID , 5000000, 0, '');
        }catch(TException $e){
            $this->assertTrue($e->getCode()==10013);
        }


        
    }

    /**
        测试解冻保证金
        @group UnFreeze
        @group Exception
    */
    public function testUnFreezeBail(){
        
        echo __METHOD__ ."\n";
        $client = $this->client;   
        $dealerID = $this->dealerID;                       
        $addAmount = 2000;
        $orderId = $this->orderID;
        $after_freeze_bail = $client->getDealerBail($dealerID);
        $after_freeze_bail = $after_freeze_bail->data;

        //执行解冻        
        $bail = $client->unfreezeBail($dealerID, $orderId, $addAmount);
        $this->chkThriftReturnBail($bail);
        $after_unfreeze_bail = $client->getDealerBail($dealerID);
        $after_unfreeze_bail = $after_unfreeze_bail->data;
        $detail = '解冻保证金,拍单:'.$orderId;
        //验证解冻
        $redis = $this->redis;
        $data = json_decode($redis->lIndex('AuctionWeaver:Bail:ChangeQueue',-1),true);   
        // echo json_encode($data,true);          
        //print_r($data);
        $this->assertTrue(array_key_exists('summary', $data));
        $this->assertTrue(array_key_exists('log', $data));
        $log = $data['log'];
        $this->assertTrue($log['dealer_id']==$dealerID );
        $this->assertTrue(time()-strtotime($log['use_time'])<10);
        $this->assertTrue($log['use_type']==3);
        $this->assertTrue( $log['occur_money']==$addAmount );
        $this->assertTrue( $log['recharge_method']==0);
        $this->assertTrue( $log['recharge_no']==0 );
        $this->assertTrue( $log['recharge_id']==0 );
        $this->assertTrue( $log['use_detail']==$detail);
        $this->assertTrue( $log['collection_id']==0);
        $this->assertTrue( $after_unfreeze_bail['bail_amount'] == ($after_freeze_bail['bail_amount']+$log['occur_money']) );
        $this->assertTrue( $data['summary']['bail_amount'] == ($after_freeze_bail['bail_amount']+$log['occur_money'] ) );
        $this->assertTrue( $data['summary']['freeze_amount'] == ($after_freeze_bail['freeze_amount']-$log['occur_money']));            
        $this->assertTrue( $data['summary']['dealer_id'] == $dealerID );
        
        
        $this->lPopLast1();
        
    }

    /**        
        @group DecAndUnFreeze
    */
    public function testFreezeBail2(){
        $this->testFreezeBail();
    }

    /**
        从冻结保证金中，扣除并解冻
        @group DecAndUnFreeze
    */
    public function testUnFreezeDecBail()
    {
        echo __METHOD__ ."\n";
        
        $client = $this->client;   
        $redis = $this->redis;
        $dealerID = $this->dealerID;        
        $amount = 2000;
        $orderId = $this->orderID;
        $after_freeze_bail = $client->getDealerBail($dealerID);
        $after_freeze_bail = $after_freeze_bail->data;
        // print_r($after_freeze_bail);
        //扣除并解冻保证金
        $deductAmount = 1500;            
        $bail = $client->unfreezeDecBail($dealerID , $orderId , $deductAmount, 0, '');
        $this->chkThriftReturnBail($bail);
        $after_deduct_bail = $client->getDealerBail($dealerID)->data;
        // print_r($after_deduct_bail);
        
        //验证解冻记录
        $data1 = json_decode($redis->lIndex('AuctionWeaver:Bail:ChangeQueue',-2),true);     
        // echo json_encode($data1,JSON_UNESCAPED_UNICODE);        
        
        // print_r($data1);
        $log1 = $data1['log'];
        $this->assertTrue($log1['dealer_id']==$dealerID );
        $this->assertTrue(time()-strtotime($log1['use_time'])<10);
        $this->assertTrue($log1['use_type']==3);        
        $this->assertTrue( $log1['occur_money'] == ($amount-$deductAmount) );
        $this->assertTrue($log1['recharge_method']==0);
        $this->assertTrue($log1['recharge_no']==0 );
        $this->assertTrue($log1['recharge_id']==0 );
        $this->assertTrue($log1['use_detail']!='');
        $this->assertTrue($log1['collection_id']==0); 
        //验证扣除记录
        $data = json_decode($redis->lIndex('AuctionWeaver:Bail:ChangeQueue',-1),true); 
        
        // echo json_encode($data,JSON_UNESCAPED_UNICODE);
        // print_r($data);
        $log = $data['log'];
        $this->assertTrue($log['dealer_id']==$dealerID );
        $this->assertTrue(time()-strtotime($log['use_time'])<10);
        $this->assertTrue($log['use_type']==5);
        $this->assertTrue($log['occur_money'] == $deductAmount );
        $this->assertTrue($log['recharge_method']==0);
        $this->assertTrue($log['recharge_no']==0 );
        $this->assertTrue($log['recharge_id']==0 );
        $this->assertTrue($log['use_detail']!='');
        $this->assertTrue($log['collection_id']==0); 
        //验证扣除并解冻后保证金总帐            
        $this->assertTrue($after_deduct_bail['bail_amount'] == $after_freeze_bail['bail_amount']+$log1['occur_money'] );
        $this->assertTrue($data1['summary']['bail_amount'] == $after_freeze_bail['bail_amount']+$log1['occur_money'] );
        $this->assertTrue($data1['summary']['freeze_amount'] == $after_freeze_bail['freeze_amount']-($log1['occur_money']+$log['occur_money']) );            
        $this->assertTrue($data1['summary']['dealer_id'] == $dealerID) ;

        $this->lPopLast1();
        $this->lPopLast1();    

    }

    
    

    /**
        测试保证金提取
        @group DecBail
    */
    public function testDecBail(){
        echo __METHOD__ ."\n";

        $client = $this->client;   
        $redis = $this->redis;
        $dealerID = $this->dealerID;        
        $amount = 500;
        $orderId = $this->orderID;
        //保证金提取
        $useDetail = '保证金提取';            
        $after_add_bail = $client->getDealerBail($dealerID)->data;
        $bail = $client->decBail($dealerID, $amount, 4, $useDetail,0,0,0,0);
        $this->chkThriftReturnBail($bail);
        $after_tiqu_bail = $client->getDealerBail($dealerID)->data;
        //验证            
        $data = json_decode($redis->lIndex('AuctionWeaver:Bail:ChangeQueue',-1),true); 
        $this->lPopLast1();
        // echo json_encode($data,JSON_UNESCAPED_UNICODE);
        //print_r($data);
        $log = $data['log'];
        $this->assertTrue($log['dealer_id']==$dealerID );
        $this->assertTrue(time()-strtotime($log['use_time'])<10);
        $this->assertTrue($log['use_type']==4);
        $this->assertTrue($log['occur_money']==$amount );
        $this->assertTrue($log['recharge_method']==0);
        $this->assertTrue($log['recharge_no']==0 );
        $this->assertTrue($log['recharge_id']==0 );
        $this->assertTrue($log['use_detail']==$useDetail);
        $this->assertTrue($log['collection_id']==0);
        $this->assertTrue($after_tiqu_bail['bail_amount'] == ($after_add_bail['bail_amount']-$log['occur_money']) );
        $this->assertTrue($data['summary']['bail_amount'] == ($after_add_bail['bail_amount']-$log['occur_money']) );
        $this->assertTrue($data['summary']['freeze_amount'] == $after_add_bail['freeze_amount']);            
        $this->assertTrue($data['summary']['dealer_id'] == $dealerID);            
            
        
    }

    /**
        @group Exception
    */
    public function testException(){
        echo __METHOD__ ."\n";        
        //保证金概述
        try{
            //车商为0
            $bailinfo = $this->client->getDealerBail(0); 
        }catch(TException $e){
            $this->assertTrue($e->getCode() == 10001);
        }

        //充值异常        
        try{
             //车商为0
            $bail = $this->client->incBail(0, 0, $detail, $rechargeNo, $rechargeId, $rechargeMethod,$collectionId);
        }catch(TException $e){
            $this->assertTrue($e->getCode() == 10001);            
        }
        try{
            //金额无效
            $bail = $this->client->incBail($this->dealerID, 0, $detail, $rechargeNo, $rechargeId, $rechargeMethod,$collectionId);
        }catch(TException $e){
            $this->assertTrue($e->getCode() == 500056);            
        }
        try {
            //金额负数
            $bail = $this->client->incBail($this->dealerID, -1, $detail, $rechargeNo, $rechargeId, $rechargeMethod,$collectionId);
        } catch (TException $e) {
            $this->assertTrue($e->getCode() == 500056);               
        }
        try {
            $bail = $this->client->incBail($this->dealerID, null, $detail, $rechargeNo, $rechargeId, $rechargeMethod,$collectionId);
        } catch (TException $e) {            
            $this->assertTrue($e->getCode() == 500056);               
        }
        try {
            //描述为空
            $bail = $this->client->incBail($this->dealerID, 2000, null, $rechargeNo, $rechargeId, $rechargeMethod,$collectionId);
        } catch (TException $e) {                               
            $this->assertTrue($e->getCode() == 500058);               
        }
        
        //提取
        try{
            //车商无效
            $this->client->decBail(0, $amount, 4, $useDetail,0,0,0,0);
        }catch(TException $e){
            $this->assertTrue($e->getCode() == 10001);            
        }        
        try{
            //use_type 无效
            $this->client->decBail($this->dealerID, 0, 0, '保证金提取',0,0,0,0);
        }catch(TException $e){
            $this->assertTrue($e->getCode() == 500057);            
        }
        try{
            //金额超大
            $this->client->decBail($this->dealerID, 5000000, 4, '保证金提取',0,0,0,0);
        }catch(TException $e){
            $this->assertTrue($e->getCode() == 10006);            
        }
        try{
            //描述为空 
            $this->client->decBail($this->dealerID, 0, 4, null,0,0,0,0);
        }catch(TException $e){            
            $this->assertTrue($e->getCode() == 500058);            
        }

        //冻结
        try{
            //车商为空 
            $this->client->freezeBail($dealerID, $addAmount, $orderId);
        }catch(TException $e){
            $this->assertTrue($e->getCode()==10001);            
        }        
        try{
            //测试未开通拍卖的车商
            $this->client->freezeBail(222, $addAmount, $orderId);
        }catch(TException $e){
            $this->assertTrue($e->getCode()==10002);            
        }
        try{
            //测试拍单有误
            $this->client->freezeBail($this->dealerID, 2000,null);
        }catch(TException $e){            
            $this->assertTrue($e->getCode()==10004);            
        }

       
        
       
    }

    /**
        清理测试的数据
        @afterClass
        @group clean 
    */
    public function testClean(){
        global $isClean;
        if ($isClean){
            echo __METHOD__ ."\n";
            $this->redis->del('AuctionWeaver:Bail:DealerBailSummary:SpecVar:'.$this->dealerID);
            $this->redis->del('AuctionWeaver:Bail:ChangeQueue');
            $this->redis->del('AuctionWeaver:Bail:OrderFreezeDealerMap:SpecVar:'.$this->orderID);
            $this->redis->del('AuctionWeaver:Bail:DealerLock:SpecVar:'.$this->dealerID);    
        }
    }

    private function lPopLast1(){
        global $isClean;        
        if ($isClean){
            $this->redis->lPop('AuctionWeaver:Bail:ChangeQueue');
        }
    }


}
